#define __MLWIP_HTTPS_C_
#include "mlwip_https.h"
#include "FreeRTOS.h"
#include "FreeRTOSConfig.h"
#include <string.h>
#include "task.h"
#include "semphr.h"
#include <sys/socket.h>
#include "cJSON.h"
#include "page.h"
#include "storage.h"
#include "wifi_event.h"
#include "log.h"

void http_server_thread(void *msg);
int get_http_command(char *http_msg, char *command);
// u8 stream_buf[15000];
u8 streatask = 0;
u8 mysemaphoreflag = 0;
extern at_os_mutex_t MuxSem_Handle;

#define PART_BOUNDARY "123456789000000000000987654321"
static const char *_STREAM_CONTENT_TYPE = "multipart/x-mixed-replace;boundary=" PART_BOUNDARY;
static const char *_STREAM_BOUNDARY = "24\r\n\r\n--" PART_BOUNDARY "\r\n\r\n";
static const char *_STREAM_PART = "Content-Type: image/jpeg\r\nContent-Length: %u\r\nX-Timestamp: %d.%06d\r\n\r\n\r\n";
void stream_task_process(void *msg);
static TaskHandle_t stream_task_hd;
char TcpWriteBlock(int sc, char *buf, uint32_t len, uint32_t size);

int get_http_command(char *http_msg, char *command)
{
    char *p_end = http_msg;
    char *p_start = http_msg;
    while (*p_start) // GET /
    {
        if (*p_start == '/')
        {
            break;
        }
        p_start++;
    }
    if (p_start == NULL)
    {
        return -1;
    }

    p_end = strchr(http_msg, '\n');
    while (p_end != p_start)
    {
        if (*p_end == ' ')
        {
            break;
        }
        p_end--;
    }
    int len = p_end - p_start;
    strncpy(command, p_start, p_end - p_start);
    return len;
}

void mhttp_server_init()
{
    //常用变量
    int ss, sc;
    struct sockaddr_in server_addr;
    struct sockaddr_in client_addr;
    int snd_size = 0; /* 发送缓冲区大小 */
    socklen_t optlen; /* 选项值长度 */
    // int optlen;
    int err;
    socklen_t addrlen;
    // int addrlen;

    //建立套接字
    ss = socket(AF_INET, SOCK_STREAM, 0);

    if (ss < 0)
    {
        printf("socket error\n");
    }

    /*设置服务器地址*/
    bzero(&server_addr, sizeof(server_addr));

    /*清零*/
    server_addr.sin_family = AF_INET;
    /*协议族*/
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY); /*本地地址*/
    server_addr.sin_port = htons(80);
    /*服务器端口*/

    /*绑定地址结构到套接字描述符*/
    err = bind(ss, (struct sockaddr *)&server_addr, sizeof(server_addr));

    if (err < 0)
    {
        printf("bind error\n");
        return -1;
    }

    /*设置侦听*/
    err = listen(ss, 7);

    if (err < 0)
    {
        printf("listen error\n");
        return -1;
    }

    addrlen = sizeof(struct sockaddr_in);
    MYPARM parm11;
    while (1)
    {
        printf("accept start\r\n");
        sc = accept(ss, (struct sockaddr *)&client_addr, &addrlen);
        if ((sc < 0) || (mysemaphoreflag > 0))
        {
            printf("accept fail sc is:%d  semaphore is:%d\r\n", sc, mysemaphoreflag);
            if (sc > 0)
            {
                close(sc);
            }
            continue;
        }

        parm11.sc = sc;
        parm11.buf = NULL;

        mysemaphoreflag++;
        http_server_thread(&parm11);
        vTaskDelay(1);
    }
}

void http_server_thread(void *msg)
{
    // printf("http_server_thread\r\n");
    MYPARM *parm11;
    parm11 = (MYPARM *)msg;

    int sc;
    char readbuffer[1024];
    int size = 0;
    char command[1024];
    char head_buf[1000];
    memset(command, 0, sizeof(command));
    memset(head_buf, 0, sizeof(head_buf));
    sc = parm11->sc;

    memset(readbuffer, 0, sizeof(readbuffer));


    while (1)
    {
        // printf("read stop\r\n");
        size = read(sc, readbuffer, 1024);
        // int rc = recv(sc, readbuffer, sizeof(readbuffer), 0);
        printf("read len:%d\r\n", size);
        printf("get:%s\r\n", readbuffer);

        if (size <= 0)
        {
            printf("size <= 0\r\n");
            break;
        }
        int len = get_http_command(readbuffer, command); //得到http 请求中 GET后面的字符串
        printf("get:%s len:%d\r\n", command, len);

        if (strcmp(command, "/") == 0)
        {
            printf("command1\r\n");
            streatask = 0;
            sprintf(head_buf, "HTTP/1.1 200 OK\r\nContent-Length: %d\r\nContent-Type: text/html;charset=UTF-8\r\n\r\n", sizeof(html_page));

            // head_buf
            // strlen(index_ov2640_html)
            // 返回html页面
            int ret = write(sc, head_buf, strlen(head_buf));
            if (ret == -1)
            {
                printf("send failed");
                close(sc);
                mysemaphoreflag--;
                return NULL;
            }
            ret = write(sc, html_page, sizeof(html_page));
            if (ret < 0)
            {
                printf("text write failed");
            }
            close(sc);
            mysemaphoreflag--;
            break;
        } 
        else if (strstr(command, "set"))
        {
            printf("set\r\n");
            streatask = 0;
            // 获取POST提交过来的数据，拿到ssid部分
            char* wifiCfg = strstr(readbuffer, "ssid");

            printf("wifiCfg: %s \r\n", wifiCfg);

            sprintf(head_buf, "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: 433\r\nAccess-Control-Allow-Origin: *\r\n\r\n");

            int ret = write(sc, head_buf, strlen(head_buf));
            if (ret == -1)
            {
                printf("send failed");
                close(sc);
                mysemaphoreflag--;
                return NULL;
            }

            // 将post参数切开，分别拿到 ssid 和 pwd
            char* ssid = strtok(wifiCfg, "&");
            char* pwd =  strtok(NULL, "&");

            // 将ssid参数切开，分别拿到 key 和 value
            char* ssidKey = strtok(ssid, "=");
            char* ssidValue = strtok(NULL, "=");
            // 将pwd参数切开，分别拿到 key 和 value
            char* pwdKey = strtok(pwd, "=");
            char* pwdValue = strtok(NULL, "=");

            
            printf("OK ssid:%s, pwd:%s  \r\n", ssidValue, pwdValue);
        
            // 创建cJSON
            cJSON *json = cJSON_CreateObject();
            cJSON_AddStringToObject(json, "ssid", ssidValue);
            cJSON_AddStringToObject(json, "pwd", pwdValue);

            char data_buf[1024];

            sprintf(data_buf, "%s\r\n\r\n", cJSON_Print(json));

            printf("OK data_buf:%s  \r\n", data_buf);
            // static char data_buf[] = "{\"ssid\":1,\"pwd\":0}";
            // ret = write(sc, data_buf, 433);
            // 将获取到的数据通过json形式返回
            ret = write(sc, data_buf, sizeof(data_buf));
            if (ret < 0)
            {
                printf("text write failed");
            }
            close(sc);
            mysemaphoreflag--;

            // ============================================
            
            // 待实现 将 wifi 信息写入 存储
            flash_erase_set(SSID_KEY, ssidValue);
            flash_erase_set(PASS_KEY, pwdValue);

            // 开启 sta 模式，连接WIFI
            // 重启设备
            LOG_W("system 2s reset ");
            vTaskDelay(2000/portTICK_PERIOD_MS);
            GLB_SW_System_Reset();

            // ============================================

            break;
        }
        else
        {
            streatask = 0;
            close(sc);
            mysemaphoreflag--;
        }
        // write(sc,readbuffer,size);

    }
    //关中断
    // free(parm11->buf);
    // vTaskDelete(NULL);
    //开中断

}

char TcpWriteBlock(int sc, char *buf, uint32_t len, uint32_t size)
{
    int ret;
    uint32_t dlen = len;
    while (dlen > size)
    {
        ret = write(sc, &buf[len - dlen], size);
        if (ret < 0)
        {
            return -1;
        }
        dlen -= size;
    }
    ret = write(sc, &buf[len - dlen], dlen);
    if (ret < 0)
    {
        return -1;
    }
    return 0;
}

void stream_task_process(void *msg)
{
    int *pcb = msg;
    char lenbuf[10];
    struct timeval tv;
    u32 current_tick;
    char head_stream_buf[1000];
    char part_buf[1000];
    u32 len = 0;
    BaseType_t xReturn = pdTRUE; /* 定义一个创建信息返回值，默认为 pdPASS */

    printf("stream_task_process\r\n");
    sprintf(head_stream_buf, "HTTP/1.1 200 OK\r\nContent-Type: multipart/x-mixed-replace;boundary=123456789000000000000987654321\r\nTransfer-Encoding: chunked\r\nAccess-Control-Allow-Origin: *\r\nX-Framerate : 60\r\n\r\n");
    int ret = write(*pcb, head_stream_buf, strlen(head_stream_buf));
    if (ret == -1)
    {
        printf("send failed");
        close(*pcb);
        mysemaphoreflag--;
        vTaskDelete(NULL);
        return NULL;
    }
    vTaskDelay(10);

    while (1)
    {
        // printf("stream_task_process while\r\n");
        xReturn = xSemaphoreTake(MuxSem_Handle,  /* 互斥量句柄 */
                                 portMAX_DELAY); /* 等待时间 */
        // current_tick = tls_os_get_time();
        // tv.tv_sec = (current_tick) / HZ;
        // tv.tv_usec = (1000000 / HZ) * (current_tick % HZ) + 100;
        tv.tv_sec = 105;
        tv.tv_usec = 2950;

        ret = write(*pcb, _STREAM_BOUNDARY, strlen(_STREAM_BOUNDARY));
        if (ret < 0)
        {
            close(*pcb);
            mysemaphoreflag--;
            printf("text write failed 1 %d", ret);
            xReturn = xSemaphoreGive(MuxSem_Handle); //给出互斥量
            // tls_gpio_write(WM_IO_PA_04, 0);
            vTaskDelete(NULL);
        }

        ret = write(*pcb, "4c\r\n", strlen("4c\r\n"));
        if (ret < 0)
        {
            close(*pcb);
            mysemaphoreflag--;
            printf("text write failed 1 %d", ret);
            xReturn = xSemaphoreGive(MuxSem_Handle); //给出互斥量
            // tls_gpio_write(WM_IO_PA_04, 0);
            vTaskDelete(NULL);
        }

        ret = write(*pcb, lenbuf, strlen(lenbuf));

        if (ret < 0)
        {
            close(*pcb);
            mysemaphoreflag--;
            printf("text write failed 2 %d", ret);
            xReturn = xSemaphoreGive(MuxSem_Handle); //给出互斥量
            // tls_gpio_write(WM_IO_PA_04, 0);
            vTaskDelete(NULL);
        }
        vTaskDelay(10);

        ret = write(*pcb, "\r\n", 2);
        if (ret < 0)
        {
            close(*pcb);
            mysemaphoreflag--;
            printf("text write failed 4 %d", ret);
            xReturn = xSemaphoreGive(MuxSem_Handle); //给出互斥量
            // tls_gpio_write(WM_IO_PA_04, 0);
            vTaskDelete(NULL);
        }
        if (streatask == 0)
        {
            printf("text write failed 5 %d", ret);
            xReturn = xSemaphoreGive(MuxSem_Handle); //给出互斥量
            // tls_gpio_write(WM_IO_PA_04, 0);
            vTaskDelete(NULL);
        }
        xReturn = xSemaphoreGive(MuxSem_Handle); //给出互斥量
        vTaskDelay(50);
    }
}
